package com.atguigu.gmall.product.service.impl;

import com.atguigu.gmall.product.service.TestService;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RReadWriteLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.Arrays;
import java.util.Collections;
import java.util.UUID;
import java.util.concurrent.TimeUnit;


@Service
public class TestServiceImpl implements TestService {


    @Autowired
    private RedisTemplate redisTemplate;

    //压力测试
/*    @Override
    public synchronized void testLock() {//1  2  1亿
        Integer num = (Integer) redisTemplate.opsForValue().get("num");
        if (!StringUtils.isEmpty(num)) {
            num++;
            redisTemplate.opsForValue().set("num", num);
        }
    }*/
   //分布式锁
    @Override
    @Transactional
    public void testLock() {//1 2
        System.out.println("==============");
        System.out.println("==============");
        System.out.println("==============");
        System.out.println("==============");
        System.out.println("==============");
        System.out.println("==============");
        System.out.println("==============");
        System.out.println("==============");
        System.out.println("==============");
        String uuid = UUID.randomUUID().toString();
        //1:上锁
        Boolean isLock = redisTemplate.opsForValue()
                .setIfAbsent("lock", uuid,3, TimeUnit.SECONDS);
        // true ： 上锁成功  false :  失败
        if(isLock){
            //成功
            try {
                Integer num = (Integer) redisTemplate.opsForValue().get("num");
                if (!StringUtils.isEmpty(num)) {
                    num++;
                    redisTemplate.opsForValue().set("num", num);
                }
                int i = 1/0;
            } finally {
                //解锁
            /*    Object value = redisTemplate.opsForValue().get("lock");
                // uuid 是自己的  到3s
                if(value.equals(uuid)){//别人拿到此锁

                    //是自己的锁  删除此锁
                    redisTemplate.delete("lock");
                }*/
                // 2. 释放锁 del
                String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return tostring(redis.call('del',KEYS[1])) else return 0 end";
                this.redisTemplate.execute(new DefaultRedisScript<>(script), Collections.singletonList("lock"), uuid);

            }
        }else{
            //失败
            testLock(); //Low
        }

    }

    @Autowired
    private RedissonClient redissonClient;
    //上读锁  读
    @Override
    public Object readLock() {
        RReadWriteLock readwriteLock = redissonClient.getReadWriteLock("readwriteLock");
        RLock rLock = readwriteLock.readLock();
        rLock.lock(10,TimeUnit.SECONDS);

        Object msg = redisTemplate.opsForValue().get("msg");
        System.out.println(msg);
        return msg;

    }
    //上写锁  写
    @Override
    public void writeLock() {
        RReadWriteLock readwriteLock = redissonClient.getReadWriteLock("readwriteLock");
        RLock rLock = readwriteLock.writeLock();
        rLock.lock(10,TimeUnit.SECONDS);
        redisTemplate.opsForValue().set("msg","0316");
    }
}
